import numpy as np
from sklearn import svm, ensemble, neighbors
from Translate import Translate
from Evaluate import Evaluate
from pre_processing import *

def train_svm_link(isEvaluate = True, task = 1):
    evaluate = Evaluate()

    if task == 0 or task == 1:

        ans = {}
        for link_id in range(100, 124):
            data0 = np.load('./data_links/traindata%d_part0_modified.npz' % link_id)
            data1 = np.load('./data_links/traindata%d_part1_modified.npz' % link_id)

            if not isEvaluate:
                # data2 = np.load('./data_links/evaldata%d_part0_modified.npz' % link_id)
                # data3 = np.load('./data_links/evaldata%d_part1_modified.npz' % link_id)
                # traindata0 = np.concatenate((data0['datas'], data2['datas']))
                # traindata1 = np.concatenate((data1['datas'], data3['datas']))
                # trainlabel0 = np.concatenate((data0['labels'], data2['labels']))
                # trainlabel1 = np.concatenate((data1['labels'], data3['labels']))
                traindata0 = data0['datas']
                traindata1 = data1['datas']
                trainlabel0 = data0['labels']
                trainlabel1 = data1['labels']
                predictlabel0 = np.zeros((len(traindata0), 6))
                predictlabel1 = np.zeros((len(traindata1), 6))
            else:
                traindata0 = data0['datas'][:-7]
                traindata1 = data1['datas'][:-7]
                trainlabel0 = data0['labels'][:-7]
                trainlabel1 = data1['labels'][:-7]
                predictlabel0 = np.zeros((len(traindata0), 6))
                predictlabel1 = np.zeros((len(traindata1), 6))

            models = {}

            for i in range(6):
                # model = svm.SVR(C=0.9,gamma=0.03)
                # model = svm.SVR(C=9, gamma=0.46)
                # model = svm.SVR(C=35, gamma=0.013)
                model = svm.SVR(C=75, gamma=0.010)
                model.fit(traindata0, trainlabel0[:,i])
                models[(i, 0)] = model
                predictlabel0[:,i] = model.predict(traindata0)

                model = svm.SVR(C=0.1, gamma=0.001)
                model.fit(traindata1, trainlabel1[:,i])
                models[(i, 1)] = model
                predictlabel1[:,i] = model.predict(traindata1)

            # MAPE_train = evaluate.evaluate_test2(predictlabel, trainlabel)
            # print 'travel time MAPE_train of link %d: ' % link_id + str(MAPE_train)

            MAPE_train_0 = evaluate.evaluate_test2(predictlabel0, trainlabel0)
            MAPE_train_1 = evaluate.evaluate_test2(predictlabel1, trainlabel1)
            # print 'travel time MAPE_train of link %d: ' % link_id + str(MAPE_train_0) + ' ' + str(MAPE_train_1)


            if not isEvaluate:
                data0 = np.load('./data_links/testdata%d_part0_modified.npz' % link_id)
                data1 = np.load('./data_links/testdata%d_part1_modified.npz' % link_id)
                testdata0 = data0['tests']
                testdata1 = data1['tests']
                testlabel = np.zeros((7, 12))
            else:
                # data0 = np.load('./data_links/evaldata%d_part0_modified.npz' % link_id)
                # data1 = np.load('./data_links/evaldata%d_part1_modified.npz' % link_id)
                testdata0 = data0['datas'][-7:]
                testdata1 = data1['datas'][-7:]
                testlabel = np.zeros((7, 12))
                reslabel = np.concatenate((data0['labels'][-7:], data1['labels'][-7:]), axis = 1)

            for i in range(6):
                testlabel[:,i] = models[(i, 0)].predict(testdata0) * 0.99
                testlabel[:,i+6] = models[(i, 1)].predict(testdata1) * 1.02

            for i in range(7):
                for j in range(12):
                    ans[(link_id,i,j)] = testlabel[i,j]

            if isEvaluate:
                MAPE_test = evaluate.evaluate_test2(testlabel, reslabel)
                # print 'travel time MAPE_test of link %d: ' % link_id + str(MAPE_test)
    
        routes = Routes()
        readRoutes(routes)
        result = np.zeros((6,7,12))
        for i in range(6):
            route = routes.routes[i]
            # print route.link_seq
            for j in range(len(route.link_seq)):
                for k in range(7):
                    for z in range(12):
                        result[i,k,z] += ans[(route.link_seq[j],k,z)]

        if not isEvaluate:
            trans = Translate()
            trans.translate(result, path = './result_svm_link', task = 1)
        else:
            data0 = np.load('./data_task1/traindata_part0_normalizing.npz')
            data1 = np.load('./data_task1/traindata_part1_normalizing.npz')
            labels = np.concatenate((data0['labels'][:,-7:,:], data1['labels'][:,-7:,:]), axis=2)
            MAPE = evaluate.evaluate_test(result, labels)
            print 'travel time MAPE: ' + str(MAPE)

        if task == 1:
            return result

if __name__ == '__main__':
	train_svm_link(isEvaluate = True, task = 1)
